package mya_dc.master_server.threads;

import java.awt.TrayIcon;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import mya_dc.master_server.MasterServerGUI;
import mya_dc.shared_classes.ConnectInfo;
import mya_dc.shared_classes.SharedDefinitions;
import mya_dc.shared_classes.Transmitter;
import mya_dc.shared_classes.SharedDefinitions.Entity;


/**
 * Handles the registrations of a new slaves on the master server.
 *
 * @author      Adam Levi
 * <br>			MYA
 */
public class SlaveListenerThread extends MYA_ConnectionThread implements Runnable
{
	/*	this class will listen on for new Slaves to come
	 * 	each new slave will open a new thread and then it will wait
	 * 	until the slave will close socket, and when it does, it will
	 * 	be erased from the hash table. 
		
	 */
	
	public SlaveListenerThread(
			MasterServerGUI ParentGUI,
			Socket slaveSocket,
			java.util.HashSet<ConnectInfo> slavesArray) throws IOException
	{
		super(
				new Transmitter(
						slaveSocket,
						null,
						SharedDefinitions.SecsBetweenTwoKeepAliveMessages));
		m_ParentGUI = ParentGUI;
		m_Socket = slaveSocket; 
		m_SlavesArray = slavesArray;
	}
	
	@Override
	public void run()
	{
		//the thread will register the slave and wait until the socket
		//will be closed
		
		//getting port number
		if (! SharedDefinitions.isExpectedEntity(m_Transmitter, Entity.ENTITY_SLAVE, true))
			return;
		int portNum = 0;
		try { portNum = (Integer)m_Transmitter.receive().getObject(); }
		catch (Exception e1) //error
		{
			m_Transmitter.close();
			return;
		}
		InetAddress address = m_Socket.getInetAddress();
		try {
			if (address.getHostName().equals("localhost") || address.getHostName().equals("127.0.0.1"))
			{
				address = InetAddress.getLocalHost();
			}
		}
		catch (UnknownHostException uhe)
		{
			address = m_Socket.getInetAddress();
		}
		m_ConnectInfo = new ConnectInfo(address.getHostAddress(),portNum); 
		registerSlave();
		try
		{
			m_Transmitter.receive();
		}
		catch(Exception e)
		{
			//the  slave is dead
		}
		m_Transmitter.close();
		unregisterSlave();
		
	}
	
	private MasterServerGUI m_ParentGUI;
	private Socket m_Socket;
	private ConnectInfo m_ConnectInfo;
	private java.util.HashSet<ConnectInfo> 	m_SlavesArray;
	
	/**
	 * Registers a new slave
	 */
	private synchronized void registerSlave()
	{
		m_SlavesArray.add(m_ConnectInfo);
		m_ParentGUI.UpdateSlavesTables();	
		m_ParentGUI.SendNotification("Information", "Accepted connection from a Compilation Slave",
				TrayIcon.MessageType.INFO);
	}
	
	/**
	 * Unregisters a new slave
	 */
	private synchronized void unregisterSlave()
	{
		m_SlavesArray.remove(m_ConnectInfo);
		m_ParentGUI.UpdateSlavesTables();
		m_ParentGUI.SendNotification("Information", "Connection terminated with a Compilation Slave",
				TrayIcon.MessageType.INFO);
	}
	
}
